package pl.edu.agh.xls2html.js;

import java.util.Stack;

import org.apache.poi.hssf.record.formula.AddPtg;
import org.apache.poi.hssf.record.formula.DividePtg;
import org.apache.poi.hssf.record.formula.IntPtg;
import org.apache.poi.hssf.record.formula.MultiplyPtg;
import org.apache.poi.hssf.record.formula.NumberPtg;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.RefPtg;
import org.apache.poi.hssf.record.formula.SubtractPtg;
import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
import org.apache.poi.hssf.record.formula.ValueOperatorPtg;

public class JSGenerator {

	private Ptg[] tokens;

	public JSGenerator(Ptg[] tokens) {
		this.tokens = tokens;
	}

	public String getJSFunction() {

		Stack<FormulaItem> stack = new Stack<FormulaItem>();
		FormulaItem formulaItem;

		for (int i = 0; i < tokens.length; i++) {
			Ptg ptg = tokens[i];
			if (ptg instanceof ValueOperatorPtg && !stack.isEmpty()) {
				formulaItem = getOperationFormula(ptg, stack);
				stack.push(formulaItem);
			} else if (ptg instanceof RefPtg) {
				formulaItem = new ReferencedFormulaValue(ptg.toFormulaString());
				stack.push(formulaItem);
			} else if (ptg instanceof NumberPtg || ptg instanceof IntPtg) {
				formulaItem = new StaticFormulaValue(ptg.toFormulaString());
				stack.push(formulaItem);
			}

		}
		if (stack.size() != 1)
			throw new IllegalStateException("Parsing formula exception");

		return stack.pop().getJSFunctionElement();
	}

	private FormulaItem getOperationFormula(Ptg ptg, Stack<FormulaItem> stack) {
		if (ptg instanceof UnaryMinusPtg)
			return new UnaryMinusFormula(stack.pop());

		if (ptg instanceof AddPtg)
			return new AddFormula(stack.pop(), stack.pop());

		if (ptg instanceof MultiplyPtg)
			return new MultipleFormula(stack.pop(), stack.pop());

		if (ptg instanceof SubtractPtg) {
			FormulaItem secondItem = stack.pop();
			FormulaItem firstItem = stack.pop();
			return new MinusFormula(firstItem, secondItem);
		}

		if (ptg instanceof DividePtg) {
			FormulaItem secondItem = stack.pop();
			FormulaItem firstItem = stack.pop();
			return new DivFormula(firstItem, secondItem);
		}

		throw new IllegalStateException("Unknown type of formula operation");

	}

}
